package com.llc.spring.cloud.gateway.zuul.component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.llc.spring.cloud.gateway.zuul.bean.Result;
import com.llc.spring.cloud.gateway.zuul.util.ExceptionUtil;
import com.llc.spring.cloud.gateway.zuul.util.IOUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * time 2018/6/22 15:59
 *
 * @author xiaojie.zhu <br>
 */
@Component
public class ResponseHandler extends ZuulFilter {
    public final static Logger LOG = LoggerFactory.getLogger(ResponseHandler.class);


    @Override
    public String filterType() {
        return "post";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        int code = currentContext.getResponseStatusCode();
        if(currentContext.getThrowable() != null){
            //发生异常
            handlerException(currentContext,currentContext.getThrowable());
            return null;
        }else{
            //处理非200请求
            if(code != 200){
                handlerError(currentContext,code);
                return null;
            }else{
                //处理成功的请求
                handlerSuccess(currentContext);
                return null;
            }
        }
    }

    private void handlerSuccess(RequestContext currentContext) {
        Result result;
        String data = "";
        try {
            data = IOUtil.toString(currentContext.getResponseDataStream(),true);
        } catch (IOException e) {
            String errMsg = "读取响应信息失败 , " + e.getMessage();
            LOG.error(errMsg , e);
            result = new Result(500 , errMsg);
            response(result);
            return;
        }

        int code = 0;
        String msg = "SUCCESS";
        Object odata = null;
        try {
            odata = JSON.parseObject(data);
            Integer tcode = ((JSONObject) odata).getInteger("code");
            if(tcode != null){
                if(tcode != 0){
                    code = tcode;
                    msg = ((JSONObject) odata).getString("msg");
                    odata = null;
                }
            }
        } catch (Exception e) {
            try {
                odata = JSON.parseObject(data , List.class);
            } catch (Exception e1) {
                odata = data;
            }
        }

        result = new Result(code , msg , odata);

        response(result);
        return;
    }

    /**
     * 处理非200的响应
     * @param currentContext
     * @param code
     */
    private void handlerError(RequestContext currentContext, int code) {
        String errMsg = "状态码：" + code;
        try {
            String s = IOUtil.toString(currentContext.getResponseDataStream(), true);
            if(s.startsWith("<html")){
                s = s.replaceAll("<[^>]*>"," , ");
            }
            errMsg = errMsg + " , " + s;
            String requestURI = currentContext.getRequest().getRequestURI();
            LOG.error("请求" + requestURI + " 失败 , " + errMsg);
        } catch (IOException e) {
            LOG.error("获取返回内容失败" ,e);
        }

        Result result = new Result(code , errMsg);
        response(result);

    }


    /**
     * 处理发生异常时
     * @param currentContext
     */
    private void handlerException(RequestContext currentContext,Throwable e) {
        String requestURI = currentContext.getRequest().getRequestURI();
        String errorMessage = ExceptionUtil.toString(e);
        LOG.error("请求:" + requestURI + " 发生异常" , e);
        errorMessage += "请求:" + requestURI + "发生异常 , " + errorMessage;
        Result result = new Result(500,errorMessage);
        response(result);
    }

    private void response(Result result){
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletResponse response = currentContext.getResponse();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        response.setStatus(200);
        try {
            PrintWriter writer = null;
            try {
                writer = response.getWriter();
                writer.write(JSON.toJSONString(result));
            } finally {
                IOUtil.close(writer);
            }
        } catch (IOException e) {
            LOG.error("响应请求发生异常",e);
        }

    }

}
